﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Runtime.InteropServices;

namespace TARLib
{
    public static class Management
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct SYSTEMTIME
        {
            public short wYear;
            public short wMonth;
            public short wDayOfWeek;
            public short wDay;
            public short wHour;
            public short wMinute;
            public short wSecond;
            public short wMilliseconds;
        }
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool SetSystemTime(ref SYSTEMTIME theDateTime);

        public static DateTime GetDataOraSQLServer()
        {
            DateTime retValue = DateTime.MinValue;

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_GetCurrentDate]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@DataOraCorrente", System.Data.SqlDbType.DateTime) { Direction = System.Data.ParameterDirection.Output });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
                retValue = (DateTime)cmd.Parameters["@DataOraCorrente"].Value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retValue;
        }

        public static ComandaCollection GetComandeFromOrdine(Ordine ordine)
        {
            ComandaCollection retValue = new ComandaCollection();

            //// Una comanda per ogni punto di distribuzione
            //List<Comanda> allComande = new List<Comanda>();
            //foreach (PuntoDistribuzione pd in ordine.Prodotti.Select(o => o.PuntoDiDistribuzione).Distinct())
            //{
            //    allComande.Add(new Comanda(
            //        null,
            //        ordine.Prodotti.Where(o=>o.PuntoDiDistribuzione==pd).ToList(),
            //        pd,
            //        ordine.TavoloAssegnato,
            //        null,
            //        ordine.Note,


            //}

            return retValue;
        }

        public static KeyValuePair<ProdottoOrdinato, string> PrenotaProdotto(Prodotto prodottoDaOrdinare, Guid ordineID, Decimal prezzoVendita, string note)
        {
            KeyValuePair<ProdottoOrdinato, string> retValue = new KeyValuePair<ProdottoOrdinato, string>(null, null);

            if (prodottoDaOrdinare.IsLimitato)
            {
                if (!Management.IsProdottoDisponibile(prodottoDaOrdinare))
                {
                    retValue = new KeyValuePair<ProdottoOrdinato, string>(
                        null,
                        "Prodotto non disponibile");
                }
                else
                {
                    // Ordinazione di un nuovo prodotto, deve essere "lockato" su DB
                    // dopo averne verificato la disponibilità
                    SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = conn;
                    cmd.CommandText = "[Cucina].[SP_ProdottoOrdinatoOrdine_I]";
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.Parameters.Add(new SqlParameter("@OrdineID", System.Data.SqlDbType.UniqueIdentifier) { Value = ordineID });
                    cmd.Parameters.Add(new SqlParameter("@ProdottoID", System.Data.SqlDbType.Int) { Value = prodottoDaOrdinare.ProdottoID });
                    cmd.Parameters.Add(new SqlParameter("@Nome", System.Data.SqlDbType.NVarChar, 100) { Value = prodottoDaOrdinare.Nome });
                    cmd.Parameters.Add(new SqlParameter("@NomeBreve", System.Data.SqlDbType.NVarChar, 20) { Value = prodottoDaOrdinare.NomeBreve });
                    cmd.Parameters.Add(new SqlParameter("@PrezzoVendita", System.Data.SqlDbType.Decimal) { Value = prezzoVendita, Precision = 10, Scale = 2 });

                    if (note == null)
                    {
                        cmd.Parameters.Add(new SqlParameter("@Note", System.Data.SqlDbType.NVarChar, 8000) { Value = DBNull.Value });
                    }
                    else
                    {
                        cmd.Parameters.Add(new SqlParameter("@Note", System.Data.SqlDbType.NVarChar, 8000) { Value = note });
                    }

                    cmd.Parameters.Add(new SqlParameter("@ProdottoOrdinatoID", System.Data.SqlDbType.UniqueIdentifier, -1) { Direction = System.Data.ParameterDirection.Output });

                    try
                    {
                        conn.Open();
                        cmd.ExecuteNonQuery();

                        retValue = new KeyValuePair<ProdottoOrdinato, string>(
                            new ProdottoOrdinato(
                                prodottoDaOrdinare.ProdottoID,
                                prodottoDaOrdinare.Nome,
                                prodottoDaOrdinare.NomeBreve,
                                new Guid(cmd.Parameters["@ProdottoOrdinatoID"].Value.ToString()),
                                prodottoDaOrdinare.PrezzoListino,
                                note,
                                prezzoVendita,
                                prodottoDaOrdinare.PuntoDiDistribuzione,
                                prodottoDaOrdinare.CodiceProdottoBarcode,
                                prodottoDaOrdinare.IsLimitato,
                                prodottoDaOrdinare.PercentualeVassoio),
                            "Prenotazione effettuata con lock del prodotto");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        cmd.Dispose();
                        conn.Close();
                        conn.Dispose();
                    }
                }
            }
            else
            {
                // Prodotto non limitato, non è necessario lock su DB
                retValue = new KeyValuePair<ProdottoOrdinato, string>(
                    new ProdottoOrdinato(
                        prodottoDaOrdinare.ProdottoID,
                        prodottoDaOrdinare.Nome,
                        prodottoDaOrdinare.NomeBreve,
                        null,
                        prodottoDaOrdinare.PrezzoListino,
                        note,
                        prezzoVendita,
                        prodottoDaOrdinare.PuntoDiDistribuzione,
                        prodottoDaOrdinare.CodiceProdottoBarcode,
                        prodottoDaOrdinare.IsLimitato,
                        prodottoDaOrdinare.PercentualeVassoio),
                    "Prenotazione effettuata senza lock del prodotto");
            }

            return retValue;
        }

        public static void EliminaPrenotazioneProdotto(ProdottoOrdinato prodottoDaRimuovere)
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_ProdottoOrdinatoOrdine_D]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@ProdottoOrdinatoID", System.Data.SqlDbType.UniqueIdentifier) { Value = prodottoDaRimuovere.CodiceOrdinazione });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public static void EliminaTuttePrenotazioniProdotto(Guid ordineID)
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_ProdottoOrdinatoOrdine_Clear]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@OrdineID", System.Data.SqlDbType.UniqueIdentifier) { Value = ordineID });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public static bool IsProdottoDisponibile(Prodotto prodottoDaVerificare)
        {
            return prodottoDaVerificare.GetDisponibilita().IsDisponibile;
        }

        public static Menu GetMenuInVigore(DateTime dataOraDaConsiderare)
        {
            Menu retValue = null;

            // Cerca un menù valido
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Menu_Data]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@TimeStamp", System.Data.SqlDbType.DateTime) { Value = dataOraDaConsiderare });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    retValue = new Menu(
                        (int)dr["MenuID"],
                        (DateTime)dr["InizioValidita"],
                        dr["FineValidita"] == DBNull.Value ? null : (DateTime?)dr["FineValidita"],
                        dr["NomeEvento"].ToString(),
                        new Guid(dr["MenuVersionGuid"].ToString()),
                        (DateTime)dr["MenuVersionTimeStamp"]);
                }
                else
                {
                    // Menù non trovato
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            if (retValue != null)
            {
                // Aggiungi i prodotti
                foreach (Prodotto p in ProdottiMenu(retValue.MenuID))
                {
                    retValue.Add(p);
                }
            }

            return retValue;
        }

        public static Menu GetMenuInVigoreSenzaProdotti(DateTime dataOraDaConsiderare)
        {
            Menu retValue = null;

            // Cerca un menù valido
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Menu_Data]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@TimeStamp", System.Data.SqlDbType.DateTime) { Value = dataOraDaConsiderare });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    retValue = new Menu(
                        (int)dr["MenuID"],
                        (DateTime)dr["InizioValidita"],
                        dr["FineValidita"] == DBNull.Value ? null : (DateTime?)dr["FineValidita"],
                        dr["NomeEvento"].ToString(),
                        new Guid(dr["MenuVersionGuid"].ToString()),
                        (DateTime)dr["MenuVersionTimeStamp"]);
                }
                else
                {
                    // Menù non trovato
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retValue;
        }

        public static Guid? GetGuidUltimaVersioneMenu()
        {
            Guid? retValue = null;

            // Cerca un menù valido
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_MenuHash_Last]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    retValue = new Guid(dr["MenuVersionGuid"].ToString());
                }
                else
                {
                    // Menù non trovato
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retValue;
        }

        private static List<Prodotto> ProdottiMenu(int menuID)
        {
            List<Prodotto> retList = new List<Prodotto>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_ProdottiMenu_CL]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@MenuID", System.Data.SqlDbType.Int) { Value = menuID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new Prodotto(
                        (int)dr["ProdottoID"],
                        dr["Nome"].ToString(),
                        dr["NomeBreve"].ToString(),
                        (Decimal)dr["PrezzoListino"],
                        new PuntoDistribuzione(
                            (int)dr["PuntoDistribuzioneID"],
                            dr["Descrizione"].ToString(),
                            (bool)dr["IsCheckInRichiesto"],
                            (bool)dr["IsStampaRemotaRichiesta"],
                            (bool)dr["IsConsegnaRichiesta"],
                            (bool)dr["IsTavoloRichiesto"],
                            dr["PathStampante"] == DBNull.Value ? null : dr["PathStampante"].ToString(),
                            (int)dr["VelocitaWidthFinestraSecondi"],
                            (int)dr["VelocitaNSuddivisioni"],
                            (int)dr["VelocitaLeftSkipPercentage"],
                            (int)dr["VelocitaRightSkipPercentage"],
                            (int)dr["GracePeriodStampaSecondi"],
                            dr["VelocitaFissaProdottiOra"] == DBNull.Value ? null : (int?)dr["VelocitaFissaProdottiOra"]),
                        dr["Barcode"].ToString(),
                        (bool)dr["IsLimitato"],
                        (int)dr["PercentualeVassoio"]));

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static List<Prodotto> GetAllProdotti()
        {
            List<Prodotto> retList = new List<Prodotto>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Prodotti_CL]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new Prodotto(
                        (int)dr["ProdottoID"],
                        dr["Nome"].ToString(),
                        dr["NomeBreve"].ToString(),
                        (Decimal)dr["PrezzoListino"],
                        new PuntoDistribuzione(
                            (int)dr["PuntoDistribuzioneID"],
                            dr["Descrizione"].ToString(),
                            (bool)dr["IsCheckInRichiesto"],
                            (bool)dr["IsStampaRemotaRichiesta"],
                            (bool)dr["IsConsegnaRichiesta"],
                            (bool)dr["IsTavoloRichiesto"],
                            dr["PathStampante"] == DBNull.Value ? null : dr["PathStampante"].ToString(),
                            (int)dr["VelocitaWidthFinestraSecondi"],
                            (int)dr["VelocitaNSuddivisioni"],
                            (int)dr["VelocitaLeftSkipPercentage"],
                            (int)dr["VelocitaRightSkipPercentage"],
                            (int)dr["GracePeriodStampaSecondi"],
                            dr["VelocitaFissaProdottiOra"] == DBNull.Value ? null : (int?)dr["VelocitaFissaProdottiOra"]),
                        dr["Barcode"].ToString(),
                        (bool)dr["IsLimitato"],
                        (int)dr["PercentualeVassoio"]));

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static List<PuntoDistribuzione> GetPuntiDistribuzioneList()
        {
            List<PuntoDistribuzione> retList = new List<PuntoDistribuzione>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_PuntiDistribuzione_CL]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new PuntoDistribuzione(
                        (int)dr["PuntoDistribuzioneID"],
                        dr["Descrizione"].ToString(),
                        (bool)dr["IsCheckInRichiesto"],
                        (bool)dr["IsStampaRemotaRichiesta"],
                        (bool)dr["IsConsegnaRichiesta"],
                        (bool)dr["IsTavoloRichiesto"],
                        dr["PathStampante"] == DBNull.Value ? null : dr["PathStampante"].ToString(),
                        (int)dr["VelocitaWidthFinestraSecondi"],
                        (int)dr["VelocitaNSuddivisioni"],
                        (int)dr["VelocitaLeftSkipPercentage"],
                        (int)dr["VelocitaRightSkipPercentage"],
                        (int)dr["GracePeriodStampaSecondi"],
                        dr["VelocitaFissaProdottiOra"] == DBNull.Value ? null : (int?)dr["VelocitaFissaProdottiOra"]));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static List<Comanda> GetComandeDaStampare(int gracePeriodInSecond, int graceCheckInPeriodInSecond)
        {
            List<Comanda> retList = new List<Comanda>();
            List<int> internalList = new List<int>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_ComandeDaStampare_L]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@GracePeriod", System.Data.SqlDbType.Int) { Value = gracePeriodInSecond });
            cmd.Parameters.Add(new SqlParameter("@GraceCheckInPeriod", System.Data.SqlDbType.Int) { Value = graceCheckInPeriodInSecond });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    internalList.Add((int)dr["ComandaID"]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            // Carica le comande
            foreach (int i in internalList)
            {
                retList.Add(new Comanda(i));
            }

            return retList;
        }

        public static string GetUsernameByUserID(int userID)
        {
            string retValue = null;

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Utenti].[SP_GetUsernameByUserID]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@UserID", System.Data.SqlDbType.Int) { Value = userID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    if (dr["Username"] != DBNull.Value)
                        retValue = dr["Username"].ToString();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retValue;
        }

        public static List<Stats.StatisticaStatoComanda> GetStatisticheComande(PuntoDistribuzione puntoDistribuzione, DateTime dataGiornata)
        {
            List<Stats.StatisticaStatoComanda> retList = new List<Stats.StatisticaStatoComanda>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Stats_StatoComande]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = puntoDistribuzione.PuntoDistribuzioneID });
            cmd.Parameters.Add(new SqlParameter("@DataGiornata", System.Data.SqlDbType.DateTime) { Value = dataGiornata });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new Stats.StatisticaStatoComanda(
                        dr["Lettera"].ToString(),
                        dr["DataOraMin"] == DBNull.Value ? null : (DateTime?)dr["DataOraMin"],
                        dr["DataOraMax"] == DBNull.Value ? null : (DateTime?)dr["DataOraMax"],
                        dr["Comande"] == DBNull.Value ? 0 : (int)dr["Comande"],
                        dr["Prodotti"] == DBNull.Value ? 0 : (int)dr["Prodotti"],
                        dr["Checked"] == DBNull.Value ? 0 : (int)dr["Checked"],
                        dr["DataOraCheckInMin"] == DBNull.Value ? null : (DateTime?)dr["DataOraCheckInMin"],
                        dr["DataOraCheckInMax"] == DBNull.Value ? null : (DateTime?)dr["DataOraCheckInMax"],
                        dr["Printed"] == DBNull.Value ? 0 : (int)dr["Printed"],
                        dr["DataOraStampaMin"] == DBNull.Value ? null : (DateTime?)dr["DataOraStampaMin"],
                        dr["DataOraStampaMax"] == DBNull.Value ? null : (DateTime?)dr["DataOraStampaMax"],
                        dr["Delivered"] == DBNull.Value ? 0 : (int)dr["Delivered"],
                        dr["DataOraConsegnaMin"] == DBNull.Value ? null : (DateTime?)dr["DataOraConsegnaMin"],
                        dr["DataOraConsegnaMax"] == DBNull.Value ? null : (DateTime?)dr["DataOraConsegnaMax"],
                        puntoDistribuzione.IsCheckInRichiesto,
                        puntoDistribuzione.IsStampaRemotaRichiesta,
                        puntoDistribuzione.IsConsegnaRichiesta));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static List<Stats.NProdottiConsegnati> GetNProdottiConsegnati(PuntoDistribuzione puntoDistribuzione, DateTime dataOraMin)
        {
            List<Stats.NProdottiConsegnati> retList = new List<Stats.NProdottiConsegnati>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Stats_ProdottiDistribuiti]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = puntoDistribuzione.PuntoDistribuzioneID });
            cmd.Parameters.Add(new SqlParameter("@DataOraMin", System.Data.SqlDbType.DateTime) { Value = dataOraMin });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new Stats.NProdottiConsegnati(
                        (DateTime)dr["DataOra"],
                        (int)dr["NProdotti"]));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static List<Stats.NProdottiInCheckIn> GetNProdottiInCheckIn(PuntoDistribuzione puntoDistribuzione)
        {
            List<Stats.NProdottiInCheckIn> retList = new List<Stats.NProdottiInCheckIn>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Stats_ProdottiCheckIn]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = puntoDistribuzione.PuntoDistribuzioneID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new Stats.NProdottiInCheckIn(
                        (int)dr["ProdottoID"],
                        (int)dr["NProdotti"]));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static void DeleteAllComandaLockedByUserID(int userID)
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_ComandaLocked_D_ByUserID]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@UserID", System.Data.SqlDbType.Int) { Value = userID });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public static int CreaNuovaComandaTavoli()
        {
            int retValue = -1;

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Utenti].[SP_UtenteComandaTavolo_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@UserID", System.Data.SqlDbType.Int, -1) { Direction = System.Data.ParameterDirection.Output });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();

                retValue = (int)cmd.Parameters["@UserID"].Value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retValue;
        }

        public static List<Incasso> GetIncassiListByUserID(int userID)
        {
            List<Incasso> retList = new List<Incasso>();

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Generale].[SP_GetIncassiByUserID_CL]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@UserID", System.Data.SqlDbType.Int) { Value = userID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    retList.Add(new Incasso(
                        (int)dr["ID"],
                        dr["Descrizione"].ToString(),
                        (Decimal)dr["DaIncassare"],
                        (Decimal)dr["Incassato"],
                        dr["Provenienza"].ToString(),
                        dr["Note"] == DBNull.Value ? null : dr["Note"].ToString(),
                        dr["Author_Insert"].ToString(),
                        (DateTime)dr["TimeStamp_Insert"],
                        (int)dr["UserIDPagante"]));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retList;
        }

        public static List<Comanda> GetLast10StampeFailed()
        {
            List<Comanda> retList = new List<Comanda>();

            List<int> internalList = new List<int>();
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_ComandaStampaRemotaFailed_L]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    internalList.Add((int)dr["ComandaID"]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            // Carica al massimo 10 comande
            foreach (int i in internalList.Take(10))
            {
                retList.Add(new Comanda(i));
            }

            return retList;
        }

        public static void InsertNewMenuHash()
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_MenuHash_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public static bool IsPuntoDistribuzioneCheckInForced(int puntoDistribuzioneID)
        {
            bool retValue = false;

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_CheckInForce_Last]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = puntoDistribuzioneID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    if (dr["Started"] != DBNull.Value)
                        retValue = (bool)dr["Started"];
                    else
                        retValue = false;
                }
                else
                {
                    retValue = false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            return retValue;
        }

        public static void InsertNewCheckInForce(int puntoDistribuzioneID, DateTime timeStamp_Insert, bool isForce)
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_CheckInForce_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = puntoDistribuzioneID });
            cmd.Parameters.Add(new SqlParameter("@TimeStamp_Insert", System.Data.SqlDbType.DateTime) { Value = DateTime.Now });
            cmd.Parameters.Add(new SqlParameter("@IsForce", System.Data.SqlDbType.Bit) { Value = isForce });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public static List<Tavolo> GetTavoliInGestione()
        {
            List<Tavolo> retList = new List<Tavolo>();

            List<string> internalList = new List<string>();
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_TavoliInGestione_L]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    internalList.Add(dr["TavoloAssegnato"].ToString());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            foreach (string s in internalList)
            {
                retList.Add(new Tavolo(s));
            }

            return retList;
        }

        public static void AzzeraTavolo(string numeroTavolo)
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_TavoloReset_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@Tavolo", System.Data.SqlDbType.NVarChar, 20) { Value = numeroTavolo });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }

        public static TimeSpan GetRitardoPuntoDistribuzione(PuntoDistribuzione pd1, PuntoDistribuzione pd2, DateTime dataOraDaValutare)
        {
            TimeSpan deltaImpostato = new TimeSpan(0, 0, 0);

            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_PuntoDistribuzionePrecedenza_S]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzionePrecedenzaID", System.Data.SqlDbType.Int) { Value = pd1.PuntoDistribuzioneID });
            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = pd2.PuntoDistribuzioneID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    deltaImpostato = new TimeSpan(0, 0, (int)dr["AttesaAggiuntivaSecondi"]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            if (deltaImpostato > new TimeSpan(0, 0, 0))
            {
                TimeSpan CodaP1 = pd1.GetLunghezzaCoda(dataOraDaValutare) ?? new TimeSpan(0, 0, 0);
                TimeSpan CodaP2 = pd2.GetLunghezzaCoda(dataOraDaValutare) ?? new TimeSpan(0, 0, 0);

                deltaImpostato = deltaImpostato.Add(CodaP1).Subtract(CodaP2);

                return (deltaImpostato.Ticks > 0 ? deltaImpostato : new TimeSpan(0, 0, 0));
            }
            else
            {
                return new TimeSpan(0, 0, 0);
            }
        }

        public static KeyValuePair<bool, string> IsOrarioConforme()
        {
            bool avvia = true;
            string messaggio = "";
            DateTime oraServer = Management.GetDataOraSQLServer();
            if (Math.Abs(oraServer.Subtract(DateTime.Now).TotalSeconds) > 60)
            {
                try
                {
                    oraServer = oraServer.ToUniversalTime();
                    SYSTEMTIME newTime = new SYSTEMTIME()
                    {
                        wDay = (short)oraServer.Day,
                        wDayOfWeek = (short)oraServer.DayOfWeek,
                        wHour = (short)oraServer.Hour,
                        wMilliseconds = (short)oraServer.Millisecond,
                        wMinute = (short)oraServer.Minute,
                        wMonth = (short)oraServer.Month,
                        wSecond = (short)oraServer.Second,
                        wYear = (short)oraServer.Year
                    };
                    bool result = SetSystemTime(ref newTime);
                    if (result)
                        messaggio = "Ora client allineata automaticamente con il server.";
                    else
                    {
                        messaggio = "L'ora client differisce da quella server per più di 1 minuto e non è stato possibile modificarla automaticamente per probabili diritti mancanti. Aggiornare l'ora client a: " + ((int)Math.Abs(oraServer.Subtract(DateTime.Now).TotalSeconds)).ToString() + " secondi";
                        avvia = false;
                    }
                }
                catch (Exception ex)
                {
                    messaggio = "L'ora client differisce da quella server per più di 1 minuto e non è stato possibile modificarla automaticamente per probabili diritti mancanti. Aggiornare l'ora client a: " + Math.Abs(oraServer.Subtract(DateTime.Now).TotalSeconds).ToString() + " secondi\nErrore:" + ex.Message;
                    avvia = false;
                }
            }

            return new KeyValuePair<bool, string>(avvia, messaggio);
        }

        public static void AggiornaPrecedenzaPD(int puntoDistribuzionePrecedenzaID, int puntoDistribuzioneID, int attesaAggiuntivaSecondi)
        {
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_PuntiDistribuzionePrecedenze_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzionePrecedenzaID", System.Data.SqlDbType.Int) { Value = puntoDistribuzionePrecedenzaID });
            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = puntoDistribuzioneID });
            cmd.Parameters.Add(new SqlParameter("@AttesaAggiuntivaSecondi", System.Data.SqlDbType.Int) { Value = attesaAggiuntivaSecondi });

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }
        }
    }
}